from fastapi import FastAPI, HTTPException, BackgroundTasks
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
from fastapi.requests import Request
import logging
from datetime import datetime
from typing import Any

from config import Config
from database import DatabaseManager
from data_collector import DataCollector
from llm_analyzer import AlibabaCloudLLM
from sentiment_analyzer import SentimentAnalyzer
from bson import ObjectId


# 日志配置
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


# 应用
app = FastAPI(title="NEV Sentiment Analysis", version="1.0.0")

# 组件实例
db_manager = DatabaseManager(Config.MONGODB_URL, Config.MONGODB_DATABASE)
llm_analyzer = AlibabaCloudLLM(Config.ALIBABA_CLOUD_API_KEY)
sentiment_analyzer = SentimentAnalyzer(db_manager, llm_analyzer)
data_collector = DataCollector()

# 静态与模板
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")


def convert_objectid_to_str(obj: Any):
    if isinstance(obj, ObjectId):
        return str(obj)
    if isinstance(obj, dict):
        return {k: convert_objectid_to_str(v) for k, v in obj.items()}
    if isinstance(obj, list):
        return [convert_objectid_to_str(i) for i in obj]
    return obj


@app.get("/", response_class=HTMLResponse)
async def dashboard(request: Request):
    try:
        stats = sentiment_analyzer.get_sentiment_statistics(7)
        trends = sentiment_analyzer.get_sentiment_trends(30)
        recent_articles = db_manager.get_articles(limit=10)
        return templates.TemplateResponse(
            "dashboard.html",
            {
                "request": request,
                "stats": stats,
                "trends": trends,
                "recent_articles": recent_articles,
            },
        )
    except Exception as e:
        logger.error(f"加载仪表板失败: {e}")
        raise HTTPException(status_code=500, detail="加载仪表板失败")


@app.get("/api/articles")
async def get_articles(limit: int = 20, skip: int = 0):
    try:
        articles = db_manager.get_articles(limit=limit, skip=skip)
        articles = convert_objectid_to_str(articles)
        total = db_manager.count_articles()
        return {"articles": articles, "total": total}
    except Exception as e:
        logger.error(f"获取文章失败: {e}")
        raise HTTPException(status_code=500, detail="获取文章失败")


@app.get("/api/sentiment/stats")
async def get_sentiment_stats(days: int = 7):
    try:
        stats = sentiment_analyzer.get_sentiment_statistics(days)
        stats = convert_objectid_to_str(stats)
        return stats
    except Exception as e:
        logger.error(f"获取情感统计失败: {e}")
        raise HTTPException(status_code=500, detail="获取情感统计失败")


@app.get("/api/sentiment/trends")
async def get_sentiment_trends(days: int = 30):
    try:
        trends = sentiment_analyzer.get_sentiment_trends(days)
        trends = convert_objectid_to_str(trends)
        return {"trends": trends}
    except Exception as e:
        logger.error(f"获取情感趋势失败: {e}")
        raise HTTPException(status_code=500, detail="获取情感趋势失败")


@app.get("/api/sentiment/daily_breakdown")
async def get_daily_breakdown(days: int = 30):
    try:
        data = db_manager.get_daily_sentiment_breakdown(days)
        return {"daily": data}
    except Exception as e:
        logger.error(f"获取每日情感分布失败: {e}")
        raise HTTPException(status_code=500, detail="获取每日情感分布失败")


@app.get("/api/keywords")
async def get_keywords(days: int = 30, limit: int = 50):
    try:
        data = db_manager.get_top_keywords(days=days, limit=limit)
        return {"keywords": data}
    except Exception as e:
        logger.error(f"获取热门关键词失败: {e}")
        raise HTTPException(status_code=500, detail="获取热门关键词失败")


@app.post("/api/collect")
async def start_data_collection(background_tasks: BackgroundTasks):
    try:
        background_tasks.add_task(collect_data_task)
        return {"message": "数据采集已启动", "status": "success"}
    except Exception as e:
        logger.error(f"启动数据采集失败: {e}")
        raise HTTPException(status_code=500, detail="启动数据采集失败")


@app.post("/api/analyze")
async def start_analysis(background_tasks: BackgroundTasks):
    try:
        background_tasks.add_task(analyze_sentiment_task)
        return {"message": "舆情分析已启动", "status": "success"}
    except Exception as e:
        logger.error(f"启动舆情分析失败: {e}")
        raise HTTPException(status_code=500, detail="启动舆情分析失败")


@app.get("/api/report")
async def generate_report(days: int = 7):
    try:
        report = sentiment_analyzer.generate_sentiment_report(days)
        return {"report": report, "generated_at": datetime.now().isoformat()}
    except Exception as e:
        logger.error(f"生成报告失败: {e}")
        raise HTTPException(status_code=500, detail="生成报告失败")


@app.get("/api/topics")
async def get_topic_analysis():
    try:
        articles = db_manager.get_articles(limit=50)
        topic_analysis = sentiment_analyzer.analyze_topic_sentiment(articles)
        topic_analysis = convert_objectid_to_str(topic_analysis)
        return topic_analysis
    except Exception as e:
        logger.error(f"获取主题分析失败: {e}")
        raise HTTPException(status_code=500, detail="获取主题分析失败")


async def collect_data_task():
    try:
        logger.info("开始数据采集任务")
        # 新闻
        articles = data_collector.collect_news_articles(
            Config.NEWS_SOURCES, Config.NEW_ENERGY_KEYWORDS
        )
        # RSS（可选）
        try:
            rss_sources = getattr(Config, "RSS_SOURCES", [])
            if rss_sources:
                rss_articles = data_collector.collect_rss_articles(
                    rss_sources, Config.NEW_ENERGY_KEYWORDS
                )
                articles.extend(rss_articles)
        except Exception as e:
            logger.error(f"RSS采集失败: {e}")

        saved = 0
        for a in articles:
            res = db_manager.save_article(a)
            if res and res.get('inserted'):
                saved += 1
        logger.info(f"数据采集完成，新增 {saved} 篇文章")
    except Exception as e:
        logger.error(f"数据采集任务失败: {e}")


async def analyze_sentiment_task():
    try:
        logger.info("开始情感分析任务")
        articles = db_manager.get_articles(limit=100)
        results = await sentiment_analyzer.analyze_articles(articles)
        logger.info(f"情感分析完成，分析了 {len(results)} 篇文章")
    except Exception as e:
        logger.error(f"情感分析任务失败: {e}")


@app.on_event("startup")
async def startup_event():
    logger.info("新能源汽车舆情分析系统启动")


@app.on_event("shutdown")
async def shutdown_event():
    logger.info("新能源汽车舆情分析系统关闭")
    db_manager.close()


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
